Skip to content

Conversation

@radofuchs
Copy link
Contributor

@radofuchs radofuchs commented Jan 19, 2026

Description

Type of change

  • Refactor
  • New feature
  • Bug fix
  • CVE fix
  • Optimization
  • Documentation Update
  • Configuration Update
  • Bump-up service version
  • Bump-up dependent library
  • Bump-up library or tool used for development (does not change the final image)
  • CI configuration change
  • Konflux configuration change
  • Unit tests improvement
  • Integration tests improvement
  • End to end tests improvement

Tools used to create PR

Identify any AI code assistants used in this PR (for transparency and review context)

  • Assisted-by: (e.g., Claude, CodeRabbit, Ollama, etc., N/A if not used)
  • Generated by: (e.g., tool name and version; N/A if not used)

Related Tickets & Documents

Checklist before requesting a review

  • I have performed a self-review of my code.
  • PR has passed all pre-merge test jobs.
  • If it is a core feature, I have added thorough tests.

Testing

  • Please provide detailed steps to perform tests related to this code change.
  • How were the fix/results from this change verified? Please provide relevant screenshots or results.

Summary by CodeRabbit

  • New Features

    • Added role-based access control (Admin, User, Viewer, Query-only) with token-based authentication and a mock JWKS service.
  • Tests

    • Added comprehensive end-to-end RBAC test suite with token/server utilities and setup/teardown support.
    • Marked several flaky scenarios to be skipped by default.
  • Chores

    • Updated container configuration, networking, and added a persistent test storage volume.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 19, 2026

Walkthrough

Adds end-to-end RBAC tests and supporting infra: a mock JWKS server (container, Dockerfile, server, token generator), RBAC configs for library/server modes, BDD feature/step files that fetch/use test tokens, docker-compose updates (service/network/volume), and test hooks to swap/restore RBAC configs.

Changes

Cohort / File(s) Summary
Docker Compose / Volumes
docker-compose.yaml, docker-compose-library.yaml
Add mock-jwks service (build context tests/e2e/mock_jwks_server, port 8000, healthcheck), declare/attach lightspeednet network, add llama-storage volume, and adjust several volume bind paths/modes.
RBAC Configurations
tests/e2e/configuration/library-mode/lightspeed-stack-rbac.yaml, tests/e2e/configuration/server-mode/lightspeed-stack-rbac.yaml
New RBAC-enabled configs: JWK-based auth, jsonpath role extraction rules, role→action authorization mappings, and storage/cache paths for tests.
E2E Features & Hooks
tests/e2e/features/rbac.feature, tests/e2e/features/environment.py
Add RBAC BDD scenarios and environment hooks to swap/restore RBAC configs around RBAC-tagged features (backup, apply RBAC config, restart container, restore).
Step Definitions
tests/e2e/features/steps/rbac.py
Add get_test_tokens() to fetch tokens from mock JWKS server and authenticate_as_role(context, role) step to set Authorization header using fetched tokens.
Mock JWKS Server
tests/e2e/mock_jwks_server/*
Add server.py serving /.well-known/jwks.json, /tokens, /health; generate_tokens.py to produce JWKS and RS256 test JWTs; and Dockerfile to run the server.
Test Registry & Minor Test Skips
tests/e2e/test_list.txt, tests/e2e/features/*.feature
Add rbac.feature to test list; add @skip annotations/comments to select existing scenarios in feature files.

Sequence Diagram(s)

sequenceDiagram
    actor Test
    participant JWKS as "Mock JWKS Server"
    participant Stack as "Lightspeed Stack"
    participant Store as "Storage/Config"

    Test->>JWKS: GET /tokens
    JWKS-->>Test: {"role": "<token>", ...}
    Test->>Test: Set Authorization: Bearer <token>
    Test->>Stack: HTTP request with Authorization (e.g., POST /query)
    Stack->>JWKS: GET /.well-known/jwks.json
    JWKS-->>Stack: JWKS {keys: [...]}
    Stack->>Stack: Verify signature, extract claims, resolve role
    Stack->>Store: Enforce authorization & process request
    Store-->>Stack: Result or error
    alt allowed
        Stack-->>Test: 200 OK (result)
    else denied
        Stack-->>Test: 403 Forbidden
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

ok-to-test

Suggested reviewers

  • tisnik
  • asimurka
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR introduces additional out-of-scope changes: skipping existing test scenarios in info.feature, query.feature, and streaming_query.feature that are unrelated to RBAC E2E tests implementation. Remove the @skip annotations and comments from info.feature, query.feature, and streaming_query.feature as these are unrelated to the RBAC E2E testing objectives.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title directly corresponds to the main objective of adding RBAC end-to-end tests, clearly identifying the feature being implemented.
Linked Issues check ✅ Passed The PR implements most core objectives from issue #636 including RBAC configuration files, mock JWKS server, feature tests, and test steps, but appears to use RBAC instead of the specified authorization_jwk naming.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@radofuchs radofuchs force-pushed the LCORE_598_RBAC_E2E_tests branch from d2fa06e to d608577 Compare January 19, 2026 10:53
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@docker-compose-library.yaml`:
- Around line 66-70: The healthcheck block currently uses curl (test key) which
isn't available in the python:3.12-slim image; update the healthcheck "test" to
invoke Python (python -c) and use the stdlib urllib.request.urlopen to GET
/health so the command succeeds on HTTP 200 and fails (non-zero exit) on errors,
replacing the curl-based invocation in the healthcheck test entry.
🧹 Nitpick comments (2)
tests/e2e/mock_jwks_server/generate_tokens.py (1)

14-20: default_backend() is deprecated in recent cryptography versions.

Since cryptography 3.x, default_backend() is no longer needed—the backend parameter can be omitted entirely. This is a minor issue for a one-time utility script.

🔧 Suggested simplification
-from cryptography.hazmat.backends import default_backend
 
 # Generate RSA key pair
 private_key = rsa.generate_private_key(
-    public_exponent=65537, key_size=2048, backend=default_backend()
+    public_exponent=65537, key_size=2048
 )
tests/e2e/features/steps/rbac.py (1)

12-33: Consider using logging instead of print for diagnostic output.

Per coding guidelines, modules should use logger = logging.getLogger(__name__) pattern. However, for BDD step definitions that run in behave's context, print statements are commonly used and captured by behave's output handling.

@radofuchs radofuchs force-pushed the LCORE_598_RBAC_E2E_tests branch 3 times, most recently from b4ee617 to ca8e27f Compare January 20, 2026 10:06
@radofuchs radofuchs assigned tisnik and unassigned tisnik Jan 20, 2026
@radofuchs radofuchs requested a review from tisnik January 20, 2026 11:33
Copy link
Contributor

@tisnik tisnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, very nice one!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@docker-compose.yaml`:
- Around line 101-116: The lightspeed-stack service needs an explicit startup
dependency on the mock-jwks service to ensure the JWKS server is healthy before
RBAC tests run; update the lightspeed-stack service's depends_on block to
include mock-jwks with condition: service_healthy so Docker will wait for
mock-jwks' healthcheck to pass (mock-jwks is the service that already defines a
healthcheck).

Comment on lines +101 to +116
# Mock JWKS server for RBAC E2E tests
mock-jwks:
build:
context: ./tests/e2e/mock_jwks_server
dockerfile: Dockerfile
container_name: mock-jwks
ports:
- "8000:8000"
networks:
- lightspeednet
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"]
interval: 5s
timeout: 3s
retries: 3
start_period: 2s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify if any service in docker-compose files should depend on mock-jwks for RBAC tests

echo "=== Checking docker-compose files for services that might need mock-jwks dependency ==="
rg -n "depends_on|mock-jwks" --type yaml -g 'docker-compose*.yaml'

echo ""
echo "=== Checking if RBAC config references the mock-jwks server ==="
fd -e yaml -e yml . tests/e2e/configuration --exec grep -l -i "jwk\|jwks\|8000" {} \; 2>/dev/null | head -5

Repository: lightspeed-core/lightspeed-stack

Length of output: 637


🏁 Script executed:

#!/bin/bash
# Get more context about the depends_on at line 87
echo "=== Context around line 87 in docker-compose.yaml ==="
sed -n '80,95p' docker-compose.yaml

echo ""
echo "=== Check all depends_on blocks in docker-compose.yaml ==="
sed -n '/depends_on:/,/^[^ ]/p' docker-compose.yaml | head -30

echo ""
echo "=== Search for mock-jwks in depends_on statements ==="
rg -B5 "mock-jwks" docker-compose.yaml | grep -A5 -B5 "depends_on"

Repository: lightspeed-core/lightspeed-stack

Length of output: 1767


🏁 Script executed:

#!/bin/bash
# Check RBAC configuration files to understand how mock-jwks is used
echo "=== Content of server-mode RBAC config ==="
head -50 tests/e2e/configuration/server-mode/lightspeed-stack-rbac.yaml

echo ""
echo "=== Search for JWKS/8000 references in RBAC config ==="
grep -n -i "jwk\|8000\|mock" tests/e2e/configuration/server-mode/lightspeed-stack-rbac.yaml

echo ""
echo "=== Check docker-compose.yaml to see which service runs RBAC tests ==="
rg -n "test|rbac|e2e" docker-compose.yaml | head -20

echo ""
echo "=== Check for any service that might need mock-jwks ==="
rg -B3 "lightspeed:" docker-compose.yaml | head -20

Repository: lightspeed-core/lightspeed-stack

Length of output: 2358


🏁 Script executed:

#!/bin/bash
# Identify which service has the depends_on at line 87
echo "=== Identify service with depends_on at line 87 ==="
sed -n '60,95p' docker-compose.yaml | head -40

echo ""
echo "=== Verify if lightspeed service currently depends on mock-jwks ==="
sed -n '/^  lightspeed:/,/^  [^ ]/p' docker-compose.yaml | grep -A10 "depends_on"

echo ""
echo "=== Check docker-compose-library.yaml for same pattern ==="
sed -n '/^  lightspeed:/,/^  [^ ]/p' docker-compose-library.yaml | grep -A10 "depends_on"

Repository: lightspeed-core/lightspeed-stack

Length of output: 1498


🏁 Script executed:

#!/bin/bash
# Get the complete lightspeed-stack service definition with depends_on
echo "=== Complete lightspeed-stack service definition ==="
sed -n '/^  lightspeed-stack:/,/^  [a-z]/p' docker-compose.yaml | head -50

echo ""
echo "=== Confirm mock-jwks is NOT in lightspeed-stack depends_on ==="
sed -n '/^  lightspeed-stack:/,/^  [a-z]/p' docker-compose.yaml | grep -c "mock-jwks"

echo ""
echo "=== Check if mock-jwks service has any depends_on ==="
sed -n '/^  mock-jwks:/,/^  [a-z]/p' docker-compose.yaml

Repository: lightspeed-core/lightspeed-stack

Length of output: 1717


🏁 Script executed:

#!/bin/bash
# Verify if lightspeed-stack service actually needs mock-jwks at startup
echo "=== Check lightspeed-stack.yaml config for RBAC/JWKS references ==="
grep -n -i "jwk\|mock-jwks" lightspeed-stack.yaml

echo ""
echo "=== Check if lightspeed-stack loads configuration at startup ==="
grep -n "load.*config\|read.*config\|auth" lightspeed-stack.yaml | head -10

echo ""
echo "=== Verify mock-jwks healthcheck reliability ==="
cat tests/e2e/mock_jwks_server/Dockerfile 2>/dev/null || echo "Dockerfile not found"

echo ""
echo "=== Check if there's a test file that documents RBAC test expectations ==="
find tests/e2e -name "*rbac*" -o -name "*auth*" | head -5

Repository: lightspeed-core/lightspeed-stack

Length of output: 789


🏁 Script executed:

#!/bin/bash
# Check how tests use the RBAC configuration
echo "=== Check if there's a test runner that manages config loading ==="
find tests/e2e -name "*.py" -o -name "*.sh" | xargs grep -l "lightspeed-stack-rbac" 2>/dev/null | head -3

echo ""
echo "=== Check if tests explicitly wait for mock-jwks ==="
grep -r "mock-jwks" tests/e2e --include="*.py" --include="*.feature" | head -10

echo ""
echo "=== Verify the actual architecture - is RBAC config loaded at startup or test-time? ==="
grep -n "load.*yaml\|load.*config" lightspeed/server.py 2>/dev/null | head -5 || echo "Checking main application startup..."
find . -name "main.py" -o -name "app.py" | xargs grep -l "config\|authentication" 2>/dev/null | head -3

Repository: lightspeed-core/lightspeed-stack

Length of output: 337


🏁 Script executed:

#!/bin/bash
# Check the test environment setup
echo "=== Test environment setup (environment.py) ==="
cat tests/e2e/features/environment.py

echo ""
echo "=== Check app startup to understand when config is loaded ==="
head -100 ./src/app/main.py

Repository: lightspeed-core/lightspeed-stack

Length of output: 14918


🏁 Script executed:

#!/bin/bash
# Final verification: confirm that config loading might fail if mock-jwks isn't ready
echo "=== Check if configuration loading validates JWKS endpoint during startup ==="
grep -r "jwk\|validate\|fetch" src/configuration --include="*.py" | head -10

echo ""
echo "=== Confirm there's no explicit wait for mock-jwks before config load in tests ==="
grep -n "mock-jwks\|8000" tests/e2e/features/environment.py

Repository: lightspeed-core/lightspeed-stack

Length of output: 305


🏁 Script executed:

#!/bin/bash
# Find configuration loading code
echo "=== Locate configuration files ==="
find . -name "configuration*" -type f | grep -E "\.py$" | head -10

echo ""
echo "=== Check lifespan context manager - does it wait for mock-jwks? ==="
grep -A10 "LIGHTSPEED_STACK_CONFIG_PATH" ./src/app/main.py

echo ""
echo "=== Final confirmation: mock-jwks NOT in lightspeed-stack depends_on ==="
sed -n '/^  lightspeed-stack:/,/^  [a-z]/p' docker-compose.yaml | grep -E "depends_on|mock-jwks"

Repository: lightspeed-core/lightspeed-stack

Length of output: 767


🏁 Script executed:

#!/bin/bash
# Check what configuration.load_configuration actually does
echo "=== Check configuration.load_configuration implementation ==="
sed -n '/def load_configuration/,/^def /p' ./src/configuration.py | head -50

echo ""
echo "=== Check if any JWKS validation happens at config load time ==="
grep -n "jwk\|fetch\|request\|validate" ./src/configuration.py

echo ""
echo "=== Verify docker-compose shows mock-jwks is independent ==="
grep -A15 "^  mock-jwks:" docker-compose.yaml | grep -E "depends_on|networks|healthcheck" -A2

Repository: lightspeed-core/lightspeed-stack

Length of output: 2372


Add mock-jwks to lightspeed-stack's depends_on to ensure RBAC test stability.

The RBAC E2E tests dynamically switch to a configuration that references http://mock-jwks:8000/.well-known/jwks.json at runtime (see environment.py:before_feature for RBAC tests). When the lightspeed-stack container restarts with this config, there's no guarantee that mock-jwks is healthy and ready to serve JWKS tokens. Without an explicit dependency, the first RBAC authentication request could fail if mock-jwks hasn't fully started.

Add the following to the lightspeed-stack service's depends_on section:

mock-jwks:
  condition: service_healthy

This ensures Docker enforces proper startup ordering for RBAC test scenarios.

🤖 Prompt for AI Agents
In `@docker-compose.yaml` around lines 101 - 116, The lightspeed-stack service
needs an explicit startup dependency on the mock-jwks service to ensure the JWKS
server is healthy before RBAC tests run; update the lightspeed-stack service's
depends_on block to include mock-jwks with condition: service_healthy so Docker
will wait for mock-jwks' healthcheck to pass (mock-jwks is the service that
already defines a healthcheck).

@radofuchs radofuchs force-pushed the LCORE_598_RBAC_E2E_tests branch from c5c24e5 to 2d3de6f Compare January 22, 2026 09:10
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@tests/e2e/mock_jwks_server/server.py`:
- Around line 8-32: The TOKENS dict in server.py contains long‑lived hardcoded
JWTs (TOKENS) which should not be committed; replace this by loading tokens at
test runtime or generating them in a helper (e.g., create a
generate_test_tokens() function or load from a tokens.json produced by the
generator) and remove the static TOKENS constant, ensure generated tokens have
short expiries and are read by the HTTP handler that serves JWKS; update any
references to TOKENS in the module to call the new loader/generator so secrets
aren’t stored in the repo.
♻️ Duplicate comments (1)
docker-compose.yaml (1)

87-91: Add mock-jwks to lightspeed-stack depends_on to avoid RBAC test flakiness.
RBAC scenarios rely on JWKS availability; without an explicit dependency, startup timing can break the first auth requests.

🛠️ Proposed fix
     depends_on:
         llama-stack:
           condition: service_healthy
         mcp-mock-server:
           condition: service_healthy
+        mock-jwks:
+          condition: service_healthy
🧹 Nitpick comments (3)
tests/e2e/mock_jwks_server/server.py (1)

62-65: Prefer module logging over print for startup output.

Using a module logger keeps test output consistent and configurable; add logger = logging.getLogger(__name__) near imports. As per coding guidelines, ...

♻️ Suggested change
-    print("Mock JWKS server on :8000")
+    logger.info("Mock JWKS server on :8000")
tests/e2e/features/steps/rbac.py (2)

3-6: Replace print with module logging for consistent step output.

Keeps output configurable and aligned with repo logging practices. As per coding guidelines, ...

♻️ Suggested change
-import os
+import logging
+import os
 import requests
 from behave import given  # pyright: ignore[reportAttributeAccessIssue]
 from behave.runner import Context

+logger = logging.getLogger(__name__)
@@
-    print(f"🔑 Authenticated as '{role}' user")
+    logger.info("🔑 Authenticated as '%s' user", role)

Also applies to: 39-40


9-17: Convert get_test_tokens() to an async function using async def and an async HTTP client.

Behave supports async step definitions natively, and the coding guidelines explicitly require async def for I/O operations. Replace requests.get() with an async HTTP client (e.g., httpx.AsyncClient or aiohttp) to follow the established patterns.

Comment on lines +8 to +32
import json
from http.server import HTTPServer, BaseHTTPRequestHandler

# Static JWKS - pre-generated RSA public key
JWKS = {
"keys": [
{
"kty": "RSA",
"kid": "test-key-1",
"use": "sig",
"alg": "RS256",
"n": "oYVHa2Map44Cbd32Ai_37P0CHnRqDU3U3MKNdHIBkkI9nl3VV1K-4GqyKmTHl6CfSDUh5_JrKJJblyY-u7MOB9kzrPn-7it2FBfmhnc8RNBRvvF2ti3_IC-an3-2t_qYP30ZtkTx4EtgbBhd6iCJFjDU6Rjl9fxtYG-jZR_91UDOyJSQnVCV9-1oRWhkA_5y6l1gNKu-Kc92Kmu39fhxOs4U8399MPI-RkGcJkGRP86xg9lNx1Linz7UzEENGvYhPf2peaUvCZSElSZcgy_EFI3Tag9-nSTDCZPmxv1ugAohMGIgtQtmBI-K30_1Mek_RPwMOXh2EX5ThVhvIbXXmw",
"e": "AQAB",
}
]
}

# Pre-generated test tokens (valid for 10 years from Jan 2026)
TOKENS = {
"admin": "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3Qta2V5LTEiLCJ0eXAiOiJKV1QifQ.eyJpYXQiOjE3NjgzNzkzMDcsImV4cCI6MjA4MzczOTMwNywic3ViIjoiYWRtaW4tdXNlci1pZCIsIm5hbWUiOiJBZG1pbiBVc2VyIiwiYWRtaW4iOnRydWUsInJvbGUiOiJhZG1pbiJ9.BFVQDG6Io59q3gYwt54c2NJEI5q3MUIXwRIlPhu3v1F9inrZOPtLKBUbjgkF6OpU5xe5ck09BsKwvuNX0gBS8iVHb4vetkd2hwqDljk8wHEOs_E8X4_3Yqoz5NFgs1Mx3fd66xuWy2TtwLaIZ3Mwx6aGERZBXBvY_5yP7HI2oUQ4jVHe6TZL4qa927YFXtNZv11DBq9FkrZRaFtACt6iikEA-UD-v4N1szWlBvn_JCsmB9gQc8txN8FfNH_h01qTJWfuqBbK-6pSpgjr9pS4dG3AuFpBucp-eaBDCGlC7kz085_I10hnZhGCoB7XD1VOTILtwdMvjB_6VFd4f-0EiQ",
"user": "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3Qta2V5LTEiLCJ0eXAiOiJKV1QifQ.eyJpYXQiOjE3NjgzNzkzMDcsImV4cCI6MjA4MzczOTMwNywic3ViIjoidXNlci1pZCIsIm5hbWUiOiJSZWd1bGFyIFVzZXIiLCJhZG1pbiI6ZmFsc2UsInJvbGUiOiJ1c2VyIn0.eocDRnf8Cbw1wEee3mmZGDyPlUGAFN8-dH9LmEChAYSSQ6g94vRhL4yoQCiDJA76Vuzmt9CJKGxHNlvmqZh82rEPezLDq0H_a3qgPZq_9uS_dzl3c-ityojbI0YBE1DWm_29vhEv9lfVaJc9EalSObN5xttq32GJ8-1kFWATgP--n5SP3omoljLxAmVMlQlU2gjB7trH7OyLLHp4-DqsUzUUXsNg1pj-BmWT7pkw36QjRfintX-GEcSMbHABX0g2CXUKuLAWsqbbyLPPtDPlPFQh6HmZna74-riWJqOYg6pL4XSUwl_DKxafjZ_wCysSULUjR_i2E6XlgBlIRAZC5A",
"viewer": "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3Qta2V5LTEiLCJ0eXAiOiJKV1QifQ.eyJpYXQiOjE3NjgzNzkzMDcsImV4cCI6MjA4MzczOTMwNywic3ViIjoidmlld2VyLWlkIiwibmFtZSI6IlZpZXdlciBVc2VyIiwiYWRtaW4iOmZhbHNlLCJyb2xlIjoidmlld2VyIn0.a_6FLiAw9cg-hUNNtdv1WyQtwkMJCmMnXXB1fOcGNyjgYSL-z3-bW12FOGH86MTxdcXKxsvfaw5FrUqOZVUitlo3AjqFdZJaZkKJO23-eMvWwaCME90wPkM6nW0L95nygkko8SkX4WWoccPBqqDRG3QxzsBxq6Lu7NdSnpz2iGlZcYwmCZdIhmBqgxuQbUPeMQlxJtoiv6AUXA8lMJbHAcftrwoQ2oWVKIRwjK4VHn-s8G5HzK3ezlDKz31kNxg74rQo4jZzlRkWVHQ2wByabyaRGCysoM7KrNuCJwjs4W_tShb9nM50zTc_jrcjeur3LbtDt3XOPNyKpVxElpAgYw",
"query_only": "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3Qta2V5LTEiLCJ0eXAiOiJKV1QifQ.eyJpYXQiOjE3NjgzNzkzMDcsImV4cCI6MjA4MzczOTMwNywic3ViIjoicXVlcnktaWQiLCJuYW1lIjoiUXVlcnkgVXNlciIsImFkbWluIjpmYWxzZSwicGVybWlzc2lvbnMiOlsicXVlcnkiXX0.fOEEnWhVajeBSGxxMhzmcHPJ1ZWoDrz-JgFGngoanbEA8NGoQcNnbZvnDGg_Jn6_4YtFwQ5NnVb50lZSw046HapLPRfbQsz2yxCzW1FaX2Jvc8-d8kciZPh_aWwxv2foAEii_8hG9ZisRvUIDoBUHmtJdxGcRcilgXywIc4BS15Cxi-Ib7RPkqsKN56vIy30-vTeV0bwcAXVjmpPiekIrFqZX-rLpFptjouSdBTF8PEvh_K1pmFteMfe1QJzonDYYNdMTOsQRy-c0KH9fX7oWhw9xJvvTlh0pDZbh1zAk6EYeiSCavq6myxRGyImNT0wQ7IuzWywsBUmLauRxf6W5Q",
"no_role": "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3Qta2V5LTEiLCJ0eXAiOiJKV1QifQ.eyJpYXQiOjE3NjgzNzkzMDcsImV4cCI6MjA4MzczOTMwNywic3ViIjoibm9yb2xlLWlkIiwibmFtZSI6Ik5vIFJvbGUgVXNlciIsImFkbWluIjpmYWxzZX0.jBpNj3HKfSwMNED8J-o3A847aJg7LBDiHJeEB_tRUYJZhd4U6wMv2iun7fpdkns6b-70qtVqOd8xd-BUOsiXNpldjVWI8GaXsqh0q63X622ZYGItMWX0BGgwg2LoQgmN2G1k0xQIs1unCQn0wDmSB6ZFBAMDDSYLpZ0KOLNknh5NUX4GJyMXYgz3FZj6my0ypxWOnmOmC4iL5HGUszq6GB-K7nu75TMOuMZh4FxhbxIvWoT59y-NVKzoTxrkU4w6s0_gfcbqjieJd0sJbp-T4xm3qap7PF4yuFjwkptfbT_hiwAgbOsguTE1LbZQXOz0tdzuORQq7J9skyt2LCjV7w",
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid committing long‑lived JWTs; load or generate them at test time.

Hard‑coding decade‑long tokens in the repo triggers secret scanners and creates reuse risk if this mock is exposed. Prefer generating tokens during test setup (or loading from a JSON file produced by the generator) and keep them out of git; keep expiries short.

🔐 Suggested refactor to load tokens from a generated JSON file
 import json
+import os
 from http.server import HTTPServer, BaseHTTPRequestHandler
+from pathlib import Path

-# Pre-generated test tokens (valid for 10 years from Jan 2026)
-TOKENS = {
-    "admin": "<move-to-tokens.json>",
-    "user": "<move-to-tokens.json>",
-    "viewer": "<move-to-tokens.json>",
-    "query_only": "<move-to-tokens.json>",
-    "no_role": "<move-to-tokens.json>",
-}
+TOKENS_PATH = Path(
+    os.getenv("E2E_TOKENS_PATH", Path(__file__).with_name("tokens.json"))
+)
+
+def _load_tokens(path: Path) -> dict[str, str]:
+    with path.open(encoding="utf-8") as f:
+        return json.load(f)
+
+# Tokens are generated at test runtime and written to TOKENS_PATH
+TOKENS = _load_tokens(TOKENS_PATH)
🧰 Tools
🪛 Gitleaks (8.30.0)

[high] 27-27: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)


[high] 28-28: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)


[high] 29-29: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)


[high] 30-30: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)


[high] 31-31: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)

🤖 Prompt for AI Agents
In `@tests/e2e/mock_jwks_server/server.py` around lines 8 - 32, The TOKENS dict in
server.py contains long‑lived hardcoded JWTs (TOKENS) which should not be
committed; replace this by loading tokens at test runtime or generating them in
a helper (e.g., create a generate_test_tokens() function or load from a
tokens.json produced by the generator) and remove the static TOKENS constant,
ensure generated tokens have short expiries and are read by the HTTP handler
that serves JWKS; update any references to TOKENS in the module to call the new
loader/generator so secrets aren’t stored in the repo.

@radofuchs radofuchs merged commit 5105f6a into lightspeed-core:main Jan 22, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants